﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>定义对象的几种方式</title>
    <script type="text/javascript">
        <!-- 工厂方式定义对象 -->
        function CreatObject(name, age) {
            var object = new Object();
            object.Name = name;
            object.Age = age;
            // 匿名函数的定义方式。
            // ShowDetail属性实际上是指向函数的指针，意味着该属性是个方法。
            object.ShowDetail = function () {
                alert(this.Name + ", " + this.Age);
            }
            return object;
        }
//        var person1 = CreatObject("zhangsan", 15);
//        person1.ShowDetail();



        <!-- 构造函数方式定义对象 -->
        function Person(name, age) {
            this.Name = name;
            this.Age = age;
            // 此处的ShowResult是匿名函数，
            // 这样每新生成一个Person对象，都要创建一个ShowResult函数。
            this.ShowResult = function () {
                alert(this.Name + ", " + this.Age);
            }
            // 用这种方式指定ShowDetail属性，
            // 所有的Person对象的ShowDetail共享一个ShowDetail函数。
            this.ShowDetail = ShowDetail;
        }
        function ShowDetail() {
            alert(this.Name + ", " + this.Age);
        }

//        alert(Person.prototype.constructor);
//        var person2 = new Person("lisi", 20);
//        person2.ShowDetail();
//        alert(person2.constructor == Person);
//        alert(person2 instanceof Person);
//        alert(person2 instanceof Object);


        <!-- 原型方式定义对象 -->
        // 缺点:1.构造函数不能传参数。
        function Student() {  }
        // 为对象增加属性
        Student.prototype.Name = "zhangsan";
        Student.prototype.Age = 15;
        // 优点：解决了上面的问题，不同的对象的ShowDetail不会创建不同的函数。而是共用一个函数。
        Student.prototype.ShowDetail = function () {
            alert(this.Name + ", " + this.Age + ", " + this.Subject);
        }
        // 属性指向的是对象。
        Student.prototype.Subject = new Array();

//        var student1 = new Student();
//        // 缺点:2.所有的对象都共用属性。
//        // Subject对象被student1和student2共享，修改student1时，student2也跟着改变。
//        student1.Subject.push("Math");
//        student1.Subject.push("English");
//        // 因为string在JS中看看作是常量，所以修改student1时，student2不会跟着改变。
//        student1.Name = "lisi";
//        student1.ShowDetail();
//        var student2 = new Student();
//        student2.ShowDetail();

//        // 删除prototype属性
//        delete Student.prototype.Name;
//        // 删除属性
//        //delete student1.Name;
//        student1.ShowDetail();


        <!-- 构造函数方式+原型方式定义对象 -->
        // 属性用构造函数的方式定义，方法用原型方式来定义。
        // 这样就使每个对象都会创建自己的属性，所有的对象又共用同一个方法。
        function User(name)
        {
            this.Name=name;
            this.Arr= new Array();
        }

        User.prototype.GetInfo = function()
        {
            alert(this.Name + ": " + this.Arr);
        }

//        var user1 = new User("zhangsan");
//        user1.Arr.push("A");
//        user1.Arr.push("B");
//        var user2 = new User("lisi");
//        user1.GetInfo();
//        user2.GetInfo();


        <!-- 动态原型方式定义对象 -->
        function User2(name)
        {
            this.Name=name;
            this.Arr= new Array();
            
            // 若不加该判断，则每定义一个对象都要新生成一个function，虽然最终所有的对象的GetInfo都共用一个function。
            // 用该判断，当定义第二个User2的对象时，就不会生成新的函数了。
            if(typeof this.GetInfo != "function")
            {
                User2.prototype.GetInfo = function()
                {
                    alert(this.Name + ": " + this.Arr);
                }
            }
        }

        var user3 = new User2("zhangsan");
        user3.Arr.push("A");
        user3.Arr.push("B");
        var user4 = new User2("lisi");
        user3.GetInfo();
        user4.GetInfo();

        
    </script>
</head>
<body>

</body>
</html>
